home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Applications / Conversion / Convert_PICT / Source / PictController.m < prev    next >
Text File  |  1993-10-02  |  25KB  |  666 lines

  1. /***********************************************************************\
  2. Controller for Convert PICT which converts graphics from PICT to eps formats.
  3. Copyright (C) 1993 David John Burrowes
  4.  
  5. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version.
  6.  
  7. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
  8.  
  9. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  10.  
  11. The author, David John Burrowes, can be reached at:
  12.     davidjohn@kira.net.netcom.com
  13.     David John Burrowes
  14.     1926 Ivy #10
  15.     San Mateo, CA 94403-1367
  16. \***********************************************************************/
  17.  
  18. /*
  19. ====================================================================
  20.     This is $Revision: 1.10 $ of this file
  21.     It was last modified by $Author: death $ on $Date: 93/04/04 23:30:20 $
  22. Note that this file was created while using the New Century Schoolbook Roman typeface.  You may find that some things line up strangely if you don't use that family.
  23.  
  24.     NOTE: This has a preference called something like USECLUTS.  This is a feature that
  25.     was dropped before the 1.0 version.  I'm leaving the hooks in just in case I later wish to
  26.     implement it.  The gist of the feature was: given a bitmap or pattern with a color lookup
  27.     table, substitute the looked up color values into the bitmap for the original indices.  This
  28.     would have the effect of making the resulting file ENORMOUSLY larger in size than
  29.     the source.  But, it would also be printable or displayable on a PS level 1 device (that had
  30.     the common color extensions, of course)
  31.  
  32. $Log:    PictController.m,v $
  33. Revision 1.10  93/04/04  23:30:20  death
  34. Sun Apr  4 23:30:20 PDT 1993
  35.  
  36. Revision 1.9  93/01/09  21:07:17  death
  37. Sat Jan  9 21:07:17 PST 1993
  38.  
  39. Revision 1.8  93/01/01  11:51:24  death
  40. Fri Jan  1 11:51:24 PST 1993
  41.  
  42. Revision 1.7  92/12/31  15:33:52  death
  43. Thu Dec 31 15:33:52 PST 1992
  44.  
  45. Revision 1.6  92/12/05  23:06:22  death
  46. Sat Dec  5 23:06:21 PST 1992
  47.  
  48.  ====================================================================
  49.  */
  50.  
  51.  #import "PictController.h"
  52. #import "PSFile.h"
  53. #import "PICTFile.h"
  54. #import "PictConverter.h"
  55. #import <appkit/Matrix.h>    // For matrix stuff for preferences setting
  56. #import "string.h"
  57. #import <appkit/Application.h>    // For NXApp
  58. #import <appkit/Listener.h>    // For NXApp
  59.  
  60.  
  61. @implementation    PictController
  62.  
  63. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  64. //    Routine:        init
  65. //    Parameters:    none
  66. //    Returns:        self
  67. //    Stores:        none
  68. //    Description:
  69. //        This overrides the defalut init method.  and sets up some strings used for
  70. //        interacting with the user. We also create the pict converter instance
  71. //        needed later.
  72. //    Bugs:
  73. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  74. - init
  75. {
  76.     static NXDefaultsVector theDefaults =
  77.     {
  78.         {PACKIMAGE, "YES"},
  79.         {USECLUTS, "NO"},
  80.         {VERBOSEPS, "NO"},
  81.         {CONVERTCHARS, "NO"},
  82.         {CONVERTPICC, DISCARDALLPICC},
  83.         {NULL, NULL}
  84.     };
  85.     CString    tempConvertString;
  86.  
  87.     [super init];
  88.     //
  89.     //    Provide silly default strings.
  90.     //
  91.     ConversionString = "Converting Mac PICT to NeXT eps";
  92.     SourcePrompt = "PICT file:";
  93.     DestPrompt = "EPS file:";
  94.     DestExtension = ".eps";
  95.     DefaultsOwner = "PICTConverter";
  96.  
  97.     NXRegisterDefaults(DefaultsOwner, theDefaults);
  98.     
  99.     PackImage = [self   GetBoolPref: PACKIMAGE];
  100.     FoldInCLUTs = [self   GetBoolPref: USECLUTS];
  101.     UseVerbosePS = [self   GetBoolPref: VERBOSEPS];
  102.     ConvertAllChars = [self  GetBoolPref: CONVERTCHARS];
  103.     tempConvertString =  [self  GetPref: CONVERTPICC];
  104.  
  105.     if (strcmp(tempConvertString, DISCARDALLPICC) == 0)
  106.         CommentOperation = DiscardPicComments;
  107.     else if (strcmp(tempConvertString, CONVERTALLPICC) == 0)
  108.         CommentOperation = ConvertPicComments;
  109.     else    // An error occurred.  But, let's just be silently lazy for the moment:
  110.         CommentOperation = ConvertPicComments;
  111.     FreeCString(tempConvertString);
  112.  
  113.     converterInst = [[PictConverter   alloc] init];
  114.     return self;
  115. }
  116.  
  117.  
  118.  
  119. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  120. //    Routine:        displayPreferences: 
  121. //    Parameters:    the object that called us
  122. //    Returns:        self
  123. //    Stores:        none
  124. //        This is called whenever we need to bring the preferences panel onto the screen.
  125. //        Using the value in our several preferences variables, we set the buttons in
  126. //        the preferences panel to reflect the current values, and then shows the panel.
  127. //    History:
  128. //        93.07.18    djb    Modified for Convert pict comment stuff.
  129. //    Bugs:
  130. //        As pointed out elsewhere, we don't really need to do this after the first time,
  131. //        since the buttons keep their own state.  So this paradigm needs revising!!
  132. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  133. -displayPreferences: target
  134. {
  135.     //
  136.     //    Get the default preference values, and compare judge what buttons to
  137.     //    highlight for the user.
  138.     //
  139.     if (PackImage == YES)
  140.         [CompressButton  selectCellWithTag: 1];
  141.     else
  142.         [CompressButton  selectCellWithTag: 0];
  143.  
  144.     if (FoldInCLUTs == YES)
  145.         [ColorTableButton  selectCellWithTag: 1];
  146.     else
  147.         [ColorTableButton  selectCellWithTag: 0];
  148.  
  149.     if (UseVerbosePS == YES)
  150.         [PSCodeSetButton  selectCellWithTag: 1];
  151.     else
  152.         [PSCodeSetButton  selectCellWithTag: 0];
  153.  
  154.     if (ConvertAllChars == YES)
  155.         [ConvertAllCharsButton  selectCellWithTag: 1];
  156.     else
  157.         [ConvertAllCharsButton  selectCellWithTag: 0];
  158.  
  159.     switch  (CommentOperation)
  160.     {
  161.         case ConvertPicComments:
  162.             [PicCommentItem  selectCellWithTag: PICCCONVERTTAG];
  163.             break;
  164.         case DiscardPicComments:
  165.             [PicCommentItem  selectCellWithTag: PICCDELETETAG];
  166.             break;
  167.         default:
  168.             //    Something is wrong.  But rather than let the user know, since this
  169.             //    isn't a commercial quality app, we just silently select the safest option.
  170.             [PicCommentItem  selectCellWithTag: PICCCONVERTTAG];
  171.             break;
  172.     }
  173.     //
  174.     //    Display the panel for the user.
  175.     //
  176.     [prefPanel    makeKeyAndOrderFront:self];
  177.     return self;
  178. }
  179.  
  180.  
  181. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  182. //    Routine:        ChangePacking: 
  183. //    Parameters:    the object that called us
  184. //    Returns:        self;
  185. //    Description:
  186. //        This method gets called whenever the user clicks on a button to change
  187. //        the setting of whether the output should be packed or not.  If the button they
  188. //        clicked on had a key of '1', then we will pack the image, otherwise we don't.
  189. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  190. -ChangePacking: sender
  191. {
  192.     if ( [[sender selectedCell] tag] == 1)
  193.         PackImage = YES;
  194.     else
  195.         PackImage = NO;
  196.  
  197.     [self   SetBoolPref: PACKIMAGE To: PackImage];
  198.  
  199.     return self;
  200. }
  201.  
  202.  
  203. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  204. //    Routine:        ChangeCLUTuse: 
  205. //    Parameters:    the object that called us
  206. //    Returns:        self
  207. //    Description:
  208. //        This method gets called whenever the user clicks on a button to change
  209. //        the setting of whether we should include wrap the clut information into a
  210. //        color bitmap being written out, or if we should write the clut separately.
  211. //        See the bitmap processing routines for more info.
  212. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  213. -ChangeCLUTuse: sender
  214. {
  215.     if ( [[sender selectedCell] tag] == 1)
  216.         FoldInCLUTs = YES;
  217.     else
  218.         FoldInCLUTs = NO;
  219.  
  220.     [self   SetBoolPref: USECLUTS To: FoldInCLUTs];
  221.  
  222.     return self;
  223. }
  224.  
  225.  
  226. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  227. //    Routine:        ChangePSCodeSet: 
  228. //    Parameters:    the object that called us
  229. //    Returns:        self
  230. //    Description:
  231. //        When the user asks to change which PS code set to use, this method is
  232. //        invoked.  If the button had a tag of one, we assume they want to use the
  233. //        'verbose' (commented) set of PS routines when writing out.  Otherwise, then
  234. //        want the dense but uncommented set.
  235. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  236. -ChangePSCodeSet: sender
  237. {
  238.     if ( [[sender selectedCell] tag] == 1)
  239.         UseVerbosePS = YES;
  240.     else
  241.         UseVerbosePS = NO;
  242.  
  243.     [self   SetBoolPref: VERBOSEPS To: UseVerbosePS];
  244.  
  245.     return self;
  246. }
  247.  
  248.  
  249.  
  250. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  251. //    Routine:        ChangeCharConversion: 
  252. //    Parameters:    the object that called us
  253. //    Returns:        self
  254. //    Description:
  255. //        Sets a flag that will govern whether we conver all, or only known type families.
  256. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  257. -ChangeCharConversion: sender
  258. {
  259.     if ( [[sender selectedCell] tag] == 1)
  260.         ConvertAllChars = YES;
  261.     else
  262.         ConvertAllChars = NO;
  263.  
  264.     [self   SetBoolPref: CONVERTCHARS To: ConvertAllChars];
  265.  
  266.     return self;
  267. }
  268.  
  269.  
  270. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  271. //    Routine:        ChangeCommentProcessing: 
  272. //    Parameters:    the object that called us
  273. //    Returns:        self
  274. //    Description:
  275. //        This is called, presumably, by the user's clicking on a button in the interface.
  276. //        That button click indicates a desire to change what the default conversion
  277. //        for PicComments should be.  So, figure out which button they pressed
  278. //        (e.g. convert the comments, or discard them) and set the default
  279. //        accordingly.
  280. //    Notes:
  281. //        At present this supports 2 forms of pic comment conversion.  I've tried to leave
  282. //        all the constants and stuff about PicComments general enough to allow one to
  283. //        add more options later (I can forsee, for instance, one that only strips out the
  284. //        bulky and unneeded PS code but leaves the rotated text instructions)
  285. //    History
  286. //        93.07.18    djb    created.
  287. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  288. - ChangeCommentProcessing: sender
  289. {
  290.     if ( [[sender selectedCell] tag] == PICCCONVERTTAG)
  291.     {
  292.         CommentOperation = ConvertPicComments;
  293.         [self   SetPref: CONVERTPICC To: CONVERTALLPICC];
  294.     }
  295.     else
  296.     {
  297.         CommentOperation = DiscardPicComments;
  298.         [self   SetPref: CONVERTPICC To: DISCARDALLPICC];
  299.     }
  300.  
  301.     return self;
  302. }
  303.  
  304.  
  305.  
  306. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  307. //    Routine:        openSourceFile: 
  308. //    Parameters:    the name of the file we are to open
  309. //    Returns:        the new file object
  310. //    Stores:        error
  311. //    Description:
  312. //        This simply attempts to open the source file.  If we are successfull, we
  313. //        return it to the caller, otherwise we return an error.
  314. //    Bugs:
  315. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  316. - openSourceFile: (roCString) theFile
  317. {
  318.     Instance    fileInstance;
  319.     [self   ResetResults];
  320.     
  321.     fileInstance = [[PICTFile alloc] initAndUse: theFile];
  322.     if ([fileInstance   GetErrorCode] == ERR_OK)
  323.         [fileInstance   OpenExistingFor: FILE_READ];
  324.     if ([fileInstance   GetErrorCode] != ERR_OK)
  325.     {
  326.         if ([fileInstance   GetErrorCode] == ERR_UNKNOWNVERSION)
  327.             [self   StoreErrorCode: ERR_CANTOPEN
  328.                 AndText: "Aborting because that doesn't seem to be a PICT file."];
  329.         else
  330.             [self   StoreErrorCode: ERR_CANTOPEN
  331.                 AndText: "Unable to open that file for some reason."];
  332.         [fileInstance   free];
  333.         fileInstance = NullInstance;
  334.     }
  335.     return fileInstance;
  336. }
  337.  
  338.  
  339. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  340. //    Routine:        openDestFile: 
  341. //    Parameters:    the name of the file we are to open
  342. //    Returns:        the new file object
  343. //    Stores:        error
  344. //    Description:
  345. //        This simply attempts to open the destination file.  If we are successfull, we
  346. //        return it to the caller, otherwise we return an error.
  347. //    Bugs:
  348. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  349. - openDestFile: (roCString) theFile
  350. {
  351.     Instance    fileInstance;
  352.     [self   ResetResults];
  353.     
  354.     fileInstance = [[PSFile alloc] initAndUse: theFile];
  355.     if ([fileInstance   GetErrorCode] == ERR_OK)
  356.         [fileInstance   ClearAndOpenFor: FILE_WRITE];
  357.     if ([fileInstance   GetErrorCode] != ERR_OK)
  358.     {
  359.         [self   StoreErrorCode: ERR_CREATEFAILED
  360.             AndText: "We were not able to create/open that file"];
  361.         [fileInstance   free];
  362.         fileInstance = NullInstance;
  363.     }
  364.     return fileInstance;
  365. }
  366.  
  367.  
  368. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  369. //    Routine:        FilterPICT:userData:error:
  370. //    Parameters:
  371. //        The data to be filtered
  372. //        A pointer to an error string for us to return.
  373. //    Returns:        self
  374. //    Stores:        none
  375. //    Description:
  376. //        Yet Another Hack (YAH(tm)).
  377. //        This method can be summarized quickly: This provides the code to implement a
  378. //        filter service Given pict data or the name of a pict file on the pasteboard, this will
  379. //        turn it into eps data on the pasteboard and return it to the caller.  By and large, the
  380. //        operation is pretty straightforward.  The one weird thing in all this is that in the case
  381. //        of PICT data on the pasteboard, we create a temporary file and write the pasteboard
  382. //        out to it.  And, then, we create another temporary file to hold the results of the
  383. //        conversion which, when done, we read in and return to the caller on the pasteboard.
  384. //        Why not just pass pointers to chunks of RAM?  Easy answer: the PICT converter only
  385. //        understands the File object, and subclasses, and I've not yet written one which
  386. //        uses ram as it's 'file'.  So, the quick and dirty soltuion was to massage the source
  387. //        data into a form that class could handle
  388. //    Bugs
  389. //        93.07.18    This doesn't deal well if the 'PICT' data doesn't look like PICT data at all.
  390. //        93.07.18    At the moment, we hide the app at the start of this method, and don't
  391. //                re-display it.  The theory here is that a filter should be out of sight,
  392. //                mostly, since it's mainly just behind-the-scenes anyway.  However,
  393. //                this whole routine brings up three issues.  First, this whole 'architecture'
  394. //                for getting set up to call the PICT Converter is stressed a bit...  It feels like
  395. //                there's too much repeated material scattered around, because the original
  396. //                structuring (user chooses both source and destination files by way of
  397. //                menus) didn't flex well with the addition of drag and drop, speaker/listener
  398. //                stuff with Convert RTF, and now this.
  399. //                Second, we might want to show the conversion window at some point,
  400. //                because long filterings can take, well, a long time, and watching the
  401. //                percent indicator would make things reassurring.  For reasons I do'nt
  402. //                understand, though (nor have I devoted lots of time to investigating)
  403. //                that beastie isn't appearing anyway right now.
  404. //                Thirdly, maybe the best solution to some of the 'hide show' issues is to not
  405. //                display a window at the outset, and have it only appear when menu coices
  406. //                are made (unless they need drag and drop?)
  407. //                Oh, and of course, we write everything out to files so we can convert it.
  408. //                I suspect we need some kinda subclass of PICT file to deal with in-ram data
  409. //    History
  410. //        93.07.18    djb    Created
  411. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  412.  
  413. - FilterPICT: myPasteboard
  414.     userData: (ConstCString) userData
  415.     error: (CString*) msg;
  416. {
  417.     char*            sourceData;
  418.     int                sourceLength;
  419.     Integer            destLength;
  420.     ByteString        pictHeader;
  421.     CString            finalString;
  422.     CString            tempString;
  423.     Instance            result;
  424.     Instance            destFile;
  425.     Instance            sourceFile;
  426.     NXAtom            filterableTypes[5];
  427.     NXAtom            sourceType;
  428.     NXAtom            returnTypes[2];
  429.     Integer            errorValue;
  430.     //
  431.     //    Hide the application.  We're a Filter, darnit! not a gaudy user interface thingie!
  432.     //
  433.     [NXApp    hide: self];
  434.     //
  435.     //    Set up array of tye pasteboard types we can deal with.
  436.     //
  437.     filterableTypes[0] = NXCreateFilenamePboardType("PICT");
  438.     filterableTypes[1] = NXCreateFilenamePboardType("pict");
  439.     filterableTypes[2] = NXCreateFilenamePboardType("macpict");
  440.     filterableTypes[3] = "PICT";
  441.     filterableTypes[4] = NULL;
  442.     //
  443.     //    Find a type that we can understand from the pasteboard.
  444.     //    LAZY ALERT:  Under some unusual circumstances, this could probably
  445.     //    return a null pointer.  Or something.  I'm not checking for this, but should be!
  446.     //
  447.     sourceType =
  448.         [myPasteboard
  449.             findAvailableTypeFrom: filterableTypes
  450.             num:4
  451.         ];
  452.     //
  453.     //    Now that we, of course, found a data type we understand, read it in it in.
  454.     //
  455.     result =
  456.         [myPasteboard
  457.             readType: sourceType
  458.             data: &sourceData
  459.             length: &sourceLength
  460.         ];
  461.     //
  462.     //    If we failed to read the data in, then return an error message, a la one of
  463.     //    NeXT's examples.  Otherwise, move on to setting up for the filtering
  464.     //
  465.     if (result == nil)
  466.         *msg = "Error: Could not get the data so as to filter it.";
  467.     else
  468.     {
  469.         //
  470.         //    Set up the PICT file to read the data from.  If the stuff was on the
  471.         //    pasteboard, then copy it to a temporary file.  If, however, the
  472.         //    pasteboard was a filename, just open the specified file.
  473.         //    Because the PICTFile object is presently read-only (sigh), then we must
  474.         //    open a temporary generic file, dump the data in, close and then reopen it.
  475.         //    What a wonder of efficiency!
  476.         //
  477.         if (strcmp(sourceType, "PICT") == 0)
  478.         {
  479.             sourceFile =  [[File  alloc] initAndUseTemporary];
  480.             [sourceFile   CreateAndOpenFor: FILE_WRITE];
  481.             //
  482.             //    Write out a bogus 512 byte header, since PICT files have to have
  483.             //    this.  Seems like a silly way to get 512 junk bytes, byt also seems
  484.             //    faster than writing out 512 individual bytes or 128 longwords
  485.             //
  486.             pictHeader = NewByteString(512);
  487.             [sourceFile   Write: 512 BytesFrom: pictHeader];
  488.             FreeByteString(pictHeader);
  489.             [sourceFile   Write: sourceLength BytesFrom: sourceData];
  490.             tempString = [sourceFile   GetPathname];
  491.             [sourceFile   CloseAndSave];
  492.             [sourceFile   free];
  493.  
  494.             sourceFile =  [[PICTFile  alloc] initAndUse: tempString];
  495.             [sourceFile   OpenExistingFor: FILE_READ];
  496.             FreeCString(tempString);
  497.         }
  498.         else    // One of the various PICT file types (.macpict, .pict, or .PICT)
  499.         {
  500.             sourceFile = [[PICTFile  alloc] initAndUse: sourceData];
  501.             [sourceFile   OpenExistingFor: FILE_READ];
  502.         }
  503.         //
  504.         //    LAZY ALERT: Naturally, there were no errors
  505.         //
  506.         //
  507.         //    Now, we can just open a temporary file for the converted data,
  508.         //    set up the user interface (strings in the window, and disabling
  509.         //    of the menu items), and call the conversion routine.
  510.         //
  511.         destFile = [[PSFile  alloc] initAndUseTemporary];
  512.         [destFile   CreateAndOpenFor: FILE_READWRITE];
  513.  
  514.         [SourceFileName    setStringValue: "PICT data"];
  515.         [SourceTitle        setStringValue: "Filtering:"];
  516.         [SourcePathTitle    setStringValue: ""];
  517.         [SourcePath        setStringValue: ""];
  518.         [DestFileName    setStringValue: "eps data"];
  519.         [DestTitle        setStringValue: "To:"];
  520.         [DestPathTitle    setStringValue: ""];
  521.         [DestPath        setStringValue: ""];
  522.         [StatusTitle        setStringValue: "Status:"];
  523.         [Status            setStringValue:  "Filtering"];
  524.  
  525.         [quitCommand    setEnabled: NO];
  526.         [hideCommand    setEnabled: NO];
  527.         [infoCommands    setEnabled: NO];
  528.         [editCommands    setEnabled: NO];
  529.         [servicesCommands setEnabled: NO];
  530.         [windowsCommands setEnabled: NO];
  531.  
  532.         [self  ConvertFrom: sourceFile To: destFile];
  533.         errorValue =  [self   GetErrorCode] ;
  534.         //
  535.         //    Restore the menu items.(isn't there a nicer way?)
  536.         //
  537.         [quitCommand    setEnabled: YES];
  538.         [hideCommand    setEnabled: YES];
  539.         [infoCommands    setEnabled: YES];
  540.         [editCommands    setEnabled: YES];
  541.         [servicesCommands setEnabled: YES];
  542.         [windowsCommands setEnabled: YES];
  543.         //
  544.         //    Do different actions, depending on whether we succeeded or not
  545.         //
  546.         if (errorValue == ERR_OK)
  547.         {
  548.             //
  549.             //    Well, amazing as it may seem, we seem to have succeeded in filtering the
  550.             //    data.  Get the results back onto the pasteboard and update the gui
  551.             //    (just in case someone turned off the 'hide' of the app above)
  552.             //
  553.             destLength = [destFile  FileSize];
  554.             [destFile   MoveTo: 0];
  555.             finalString = NewByteString(destLength);
  556.             [destFile   Read: destLength BytesInto: finalString];
  557.     
  558.             returnTypes[0] = NXPostScriptPboardType;
  559.             [myPasteboard declareTypes: returnTypes num: 1 owner: nil]; 
  560.             [myPasteboard writeType: NXPostScriptPboardType
  561.                     data: finalString length: destLength];
  562.             FreeByteString(finalString);
  563.  
  564.             [SourceTitle    setStringValue: "Filtered:"];
  565.             [Status    setStringValue: "Filtered successfully."];
  566.             [self StoreErrorCode:  ERR_OK AndText: "Filtering process done"];
  567.         }
  568.         else
  569.         {
  570.             //
  571.             //    Return a pretty trivial eps file, so nothing barfs if it looks. Set an
  572.             //    error return string, modify the user interface.
  573.             //
  574.             finalString = "%!PS-Adobe-3.0 EPSF-3.0\n%%BoundingBox: 0 0 0 0\n%%EndComments";
  575.             returnTypes[0] = NXPostScriptPboardType;
  576.             returnTypes[1] = NULL;
  577.             [myPasteboard declareTypes: returnTypes num: 1 owner: nil]; 
  578.             [myPasteboard writeType: NXPostScriptPboardType
  579.                     data: finalString length: strlen(finalString)];
  580.             *msg = "Error: Could not filter that (was it really PICT data?).";
  581.  
  582.             [SourceTitle    setStringValue: "Failed:"];
  583.             tempString = [self   GetErrorText];
  584.             [Status    setStringValue: tempString];
  585.             FreeCString(tempString);
  586.         }
  587.         //
  588.         //    Close the destination file, and deal with the source (if we created it,
  589.         //    delete it.  It we did not, then just close it)
  590.         //
  591.         [destFile   CloseAndDelete];
  592.  
  593.         if (strcmp(sourceType, "PICT") == 0)
  594.             [sourceFile   CloseAndDelete];
  595.         else
  596.             [sourceFile   Close];
  597.         //
  598.         //    Unlike the NeXT example, we're going to actually release the
  599.         //    data when done.
  600.         //
  601.         [myPasteboard  deallocatePasteboardData: sourceData  length: sourceLength ];
  602.     }
  603.  
  604.     return self;
  605.  
  606. }
  607.  
  608.  
  609.  
  610. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  611. //    Routine:        ConvertFrom:To: 
  612. //    Parameters:
  613. //        The file to be converted from
  614. //        the file to be converted to
  615. //    Returns:        self
  616. //    Stores:        error
  617. //    Description:
  618. //        This asks the super class to do any initalizing it needs to, and then goes
  619. //        ahead and asks the converter object to go at it.
  620. //        Before we do the conversion, though, we turn off the conversion menu item,
  621. //        set up a string describing where to find the PS source code, and
  622. //        set a couple settings in the converter instance.  Once we are finished, we
  623. //        re-enable the menu item, and store any error information.
  624. //    Bugs
  625. //    History
  626. //        93.07.18    djb    Added nxping() cal.  This should help to ensure that all the
  627. //                    gui updates of menus, etc, have been flushed to the screen.. 
  628. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  629. - ConvertFrom: sourceFile To: destinationFile
  630. {
  631.     CString        CodeSet = NewCString(strlen(AppHome)+20);
  632.     CString        tempString;
  633.     [self   ResetResults];
  634.     [ConvertCommand    setEnabled: NO];
  635.     [super   ConvertFrom: sourceFile To: destinationFile];
  636.  
  637.     if (UseVerbosePS == YES)
  638.         sprintf(CodeSet, "%s/%s", AppHome, "CommentedPSCode/");
  639.     else
  640.         sprintf(CodeSet, "%s/%s", AppHome, "UncommentedPSCode/");
  641.     
  642.     [converterInst    SetImagePacking: PackImage UsingPSIn: CodeSet];
  643.     [converterInst    SetConvertAllChars: ConvertAllChars];
  644.     [converterInst    SetPicCommentConversion: CommentOperation];
  645.     NXPing();
  646.     [converterInst    ConvertPICTfile: sourceFile ToEPSfile: destinationFile];
  647.     [ConvertCommand    setEnabled: YES];
  648.     FreeCString(CodeSet);
  649.     
  650.     if ( [converterInst   GetErrorCode] < ERR_OK)
  651.     {
  652.         tempString =   [converterInst   GetErrorText];
  653.         [self   StoreErrorCode:  [converterInst   GetErrorCode]
  654.             AndText: tempString];
  655.         FreeCString(tempString);
  656.     }
  657.     else
  658.         [self   StoreErrorCode: ERR_OK
  659.             AndText: "Converted Successfully" ];
  660.     return self;
  661. }
  662.  
  663.  
  664.  
  665.  
  666. @end